#define _LINUX_ 


#include "PPMC/PPMC.h"
#include "Hash/c_hash.h"

#include <cstdio>
#include <cstring>
#include <cstdlib>

int cod_exit=0;
char* nombre_archivo;


#define MODO_COMPRIMIR 1
#define MODO_DESCOMPRIMIR 2
#define MODO_COMP_DESC 3
#define MODO_DUMP 4


#define MODO_ARBOL 1
#define MODO_HASH 2


/* AGREGA registro A LA LISTA DE registroS A INDEXAR */
int agregar_registro(const char* clave, const char* valor )
{
printf ("...Agregando clave: %s, valor: %s \n",clave,valor);
return cod_exit;
}

int modificar_registro(const char* clave, const char* valor )
{
printf ("...Modficando clave: %s, valor: %s \n",clave,valor);
return cod_exit;
}

int quitar_registro(const char* clave)
{
printf ("...Eliminando clave: %s\n",clave);
return cod_exit;

}

int buscar_registro(const char* clave)
{

printf ("...Busando clave: %s\n",clave);
return cod_exit;

return cod_exit;
}





int dump_hash (char* nombre_archivo)
{

    c_hash arch_hash(nombre_archivo);   

    arch_hash.dump(stdout);
    
return cod_exit;

}





/* LINEA DE COMANDOS */
int mostrar_opciones (char * nombre_del_programa)
{
	  printf ("\nUsar: %s  NombreArchivo [opciones] ",nombre_del_programa);
	  printf ("\n-f [path archivo trabajo]\tIndica el archivo de trabajo");
	  printf ("\n-i [path archivo entrada]\tIndica el archivo a comprimir o descomprimir");
	  printf ("\n-c orden\tIndica que se quiere comprimir y el orden");
	  printf ("\n-d orden\tIndica que se quiere descomprimir y el orden");
	  	  	 
	  printf ("\n-v \t\tPara ver el contenido del archivo de trabajo");
	  printf ("\n-w [numero de bloque]\tPara ver el contenido de determinado bloque del archivo de trabajo");
	  
	  printf ("\nEjemplo: para comprimir: %s -c 2 -f arbol.dat -i prueba.txt",nombre_del_programa);
	  printf ("\nEjemplo: para descomprimir: %s -d 2 -f arbol.dat -i prueba.txt\n",nombre_del_programa);

	  printf ("\n-e \t Emite estadisticas");
	  printf ("\n-H \t Modo hash (en lugar de arbol)");
	  
	  
	  printf ("\n");
return 0;
}


/********************************************************************************************/

/*** OSCAR ****/
int procesar (int modo, int modo_hash, int modo_estadisticas, int orden, char* archivo_de_trabajo , char *archivo_a_procesar)
 {

	PPMC *ppmc = NULL;

	EstrategiaPPMC *estrategia = NULL;

	bool estadistica = modo_estadisticas==1?true:false;

	if ( (modo== MODO_COMPRIMIR )|| (modo== MODO_COMP_DESC  ) ) {

		
		if (modo_hash==MODO_ARBOL){
			estrategia = new PPMC_Arbol(archivo_de_trabajo);

		}
		else
			if(modo_hash==MODO_HASH) {

			estrategia = new PPMC_Hash(archivo_de_trabajo);
			}
	
		ppmc = new PPMC(orden,estrategia,estadistica);

		ppmc->comprimir(archivo_a_procesar);

		delete ppmc;
	
	}


	if ( (modo== MODO_DESCOMPRIMIR )|| (modo== MODO_COMP_DESC  ) ) {
	
		if (modo_hash==MODO_ARBOL){
					   estrategia = new PPMC_Arbol(archivo_de_trabajo);

					   }
			else
				if(modo_hash==MODO_HASH) 
				{
				estrategia = new PPMC_Hash(archivo_de_trabajo);
				}

		ppmc = new PPMC( orden, estrategia,estadistica);

		ppmc->descomprimir(archivo_a_procesar);

		delete ppmc;
	}
return 0;
}

/********************************************************************************************/

int main (int argc, char **argv)
{


int arg_pf=0; int arg_pi=0; int arg_pc=0;  int arg_pd=0; int arg_pv=0;  int arg_pw=0; 

char *archivo_de_trabajo=NULL;
char *archivo_a_procesar=NULL;

unsigned int  orden;

unsigned int NroBloque;
int modo=0;  
int modo_hash=MODO_ARBOL;
int modo_estadisticas=0;

int error=0;
int i;

/* char* clave=NULL;
char* valor=NULL;
*/

/*************************************************************************************************/

    if (argc <= 3)
	{
	  mostrar_opciones (argv[0]);
	  return 0;
	}
    else

	{
	    nombre_archivo=argv[1];
	    
	    for (i=1;i<argc;i++)
		{
		
		      /* printf("\n++++ Analizando %s",argv[i]);  */
		      
	              if(arg_pf) {  if (archivo_de_trabajo==NULL) archivo_de_trabajo=argv[i];
                                     	printf ("\n\tArchivo de trabajo: %s\n",archivo_de_trabajo);	        		      
	        		        /* agregar_registro(clave,valor);*/	        		      	        		        	        		        
	        		        arg_pf=0;	        		        
    	    			    }

	            else  if(arg_pi) {  if (archivo_a_procesar==NULL) archivo_a_procesar=argv[i];
	        	 		printf ("\n\tArchivo a procesar: %s\n",archivo_a_procesar);	        		      
	        		        /* agregar_registro(clave,valor);*/	        		      	        		        	        		        
	        		        arg_pi=0;	        		    
    	    			    }




	            else if(arg_pc) { orden=atoi(argv[i]);
	                              modo=MODO_COMPRIMIR;
	                              printf ("\n\tOrden de compresion %d\n",orden);	        		      
	        		      arg_pc=0;
    	    			    }



	            else if(arg_pd) { orden=atoi(argv[i]);
	                              modo=MODO_DESCOMPRIMIR;
	                              printf ("\n\tOrden de descompresion %d\n",orden);	        		      
	        		      arg_pd=0;
    	    			    }

		    else if (!strcmp(argv[i],"-e")) {

					        printf ("\n Opcion -H: Modo estadisticas\n");
					        modo_estadisticas=1;
		    				}




		    else if (!strcmp(argv[i],"-H")) {
					
					        printf ("\n Opcion -H: Modo Hash\n");
					        modo_hash=MODO_HASH;
		    				}		    						    				



		    else if (!strcmp(argv[i],"-v")) {
						arg_pv=1;
					        printf ("\n Opcion -v: Mostrar los datos de la estructura\n");
					        modo=MODO_DUMP;
		    				}		    						    				


		    else if (!strcmp(argv[i],"-f")) 
		    		    		if(i>=argc-1)
						        { 
						           printf ("\nOpcion -f: Falta el archivo de trabajo");						           
						           error=1;
							}		    
						else {
						arg_pf=1;
					        printf ("\nOpcion -f: Indica el archivo de trabajo");
		    				}		    						    				


		    else if (!strcmp(argv[i],"-i")) 
		    		    		if(i>=argc-1)
						        { 
						           printf ("\nOpcion -i: Falta el archivo a procesar");						           
						           error=1;
							}		    
						else {
						arg_pi=1;
					        printf ("\nOpcion -i: Indica el archivo a procesar");
		    				}		    						    				

		    else if (!strcmp(argv[i],"-c")) 
		    		    		if(i>=argc-1)
						        { 
						           printf ("\nOpcion -c: Falta el orden con el que se quiere comprimir");						           
						           error=1;
							}		    
						else {
						arg_pc=1;
					        printf ("\nOpcion -c: Indica que se va comprimir el archivo");
		    				}		    						    				


		    else if (!strcmp(argv[i],"-d")) 
		    		    		if(i>=argc-1)
						        { 
						           printf ("\nOpcion -c: Falta el orden con el que se quiere descomprimir");						           
						           error=1;
							}		    
						else {
						arg_pd=1;
					        printf ("\nOpcion -c: Indica que se va descomprimir el archivo");
		    				}		    						    				



		    else if (!strcmp(argv[i],"-w")) 
		    		    		if(i>=argc-1)
						        { 
						           printf ("\nOpcion -c: Falta el bloque que se quiere visualizar");						           
						           error=1;
							}		    
						else {
						arg_pw=1;
					        printf ("\nOpcion -c: Indica que se quiere visualizar un bloque");
		    				}		    						    				



		    				
		    				
		    else if (!strcmp(argv[i],"-h")) {
						    mostrar_opciones (argv[0]);
					        
		    				}




		    else 	{

					        printf ("\n Opcion invalida\n");
					    
					        return(-1);
			        }



		}

	  }


/*************************************************************************************************/


switch (modo)
{
    case  MODO_COMPRIMIR:  { 
			    if ( archivo_de_trabajo && archivo_a_procesar)
			     {
				if ( (orden>0) && (orden<100))
				     {
				     printf("\nComprimiendo %s con orden %d usando arhivo de trabajo %s...\n",archivo_a_procesar ,orden,archivo_de_trabajo);

				     procesar (modo,modo_hash,modo_estadisticas,orden,archivo_de_trabajo,archivo_a_procesar);
				     
				     }
				     else printf("\nOrden de compresion no valido\n"); 			   				    
			      } else printf ("\nFalta especificar el arhivo a procesar y/o el de trabajo\n");
			  break;
			    }
			    
    case  MODO_DESCOMPRIMIR:
    { 
			    if ( archivo_de_trabajo && archivo_a_procesar)
			     {
				if ( (orden>0) && (orden<100))
				    {
				     printf("\nDescomprimiendo %s con orden %d usando arhivo de trabajo %s...\n",archivo_a_procesar ,orden,archivo_de_trabajo);
				     
				     procesar (modo,modo_hash,modo_estadisticas,orden,archivo_de_trabajo,archivo_a_procesar);
				     				     
				     }
				     else printf("\nOrden de descompresion no valido\n"); 			   				    
			      } else printf ("\nFalta especificar el arhivo a procesar y/o el de trabajo\n");
			  break;
			    }
    case  MODO_DUMP: {
		       if (archivo_de_trabajo)
		       {
		    	    if (modo_hash=MODO_HASH)
			    {
		        
			    dump_hash(archivo_de_trabajo);	        
		        
    		    	    }
		    	    else if (modo_hash=MODO_ARBOL)
		    	    {
		    	    printf("No implementado\n");
		       
		    	     }
		    	     
		       
		       } else printf("Falta especificar el archivo de trabajo\n");
    
    
			break;
		      }			    
    			        			        			        			    
			    
    default	: break;
}    
    


/*************************************************************************************************/

	  return (cod_exit);
}









